﻿using System;

using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace Acid.Graphics
{
    unsafe public class VertexBuffer :  IDisposable
    {
        private int               count;
        private VertexDeclaration vertexDeclaration;
        private List<List<float>> streams;

        public VertexBuffer(VertexDeclaration vertexDeclaration)
        {
            this.vertexDeclaration = vertexDeclaration;

            this.streams           = new List<List<float>>();
        }

        public VertexDeclaration VertexDeclaration
        {
            get { return this.vertexDeclaration; }
        }

        public List<List<float>> Streams
        {
            get { return streams; }
        }

        /// <summary>
        /// Rather complex means of Packaging the Data. Couldnt Get Interleaved Arrays
        /// To pass correctly to the Graphics Card. Opted for this instead. 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        public void SetData<T>(T[] data) where T : struct
        {
            GCHandle gch = GCHandle.Alloc(data, GCHandleType.Pinned);

            IntPtr   iptr = gch.AddrOfPinnedObject();

            float * ptr = (float*)iptr.ToPointer();

            for (int i = 0; i < this.vertexDeclaration.Elements.Count; i++)  this.streams.Add(new List<float>());
             
            for (int i = 0; i < data.Length; i++)
            {
                for (int j = 0; j < vertexDeclaration.Elements.Count; j++)
                {
                    int index = (i * (vertexDeclaration.Elements[j].Stride / 4)) + (vertexDeclaration.Elements[j].Ordinal / 4);

                    for (int k = 0; k < vertexDeclaration.Elements[j].TypeCount; k++)
                    {
                        int attr_index = index + k;

                        this.streams[j].Add(ptr[attr_index]);
                    }
                }
            }

            gch.Free();
        }

        

        

        #region IDisposible Members

        private bool disposed = false;

        private void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    
                }

                this.disposed = true;
            }
        }

        public void Dispose()
        {
            this.Dispose(true);
        }

        ~VertexBuffer()
        {
            this.Dispose(false);
        }

        #endregion
    }

}
